release: PLAN33 Orca 対応(コンテナを SSH target として接続可能に)#81
Conversation
* chore: PLAN33-port-publish Draft PR 作成 * feat(compose): ENABLE_SSH 時に SSH ポートを決定的に publish (PLAN33 PR2) Orca からコンテナへ SSH 接続できるよう、ENABLE_SSH=true のとき generate_scaled_compose が各 dev-<index> サービスへ <bind>:<port>:22 を publish する。 - env/keys.py: ENABLE_SSH / DEVBASE_SSH_BIND / DEVBASE_SSH_PORT_BASE を追加 - volume/ports.py (新規): sha1 ベースの安定ハッシュで (project, index) → host port を決定的に算出 (down→up を跨いで一定) - volume/compose.py: project_name を _build_scaled_services / _build_dev_instance へ通し、ENABLE_SSH 有効時のみ ports を注入 - tests/volume/test_compose_ssh_ports.py (新規): 有効/無効・bind・base・ 決定性・衝突回避の単体テスト Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: PLAN33-base-sshd Draft PR 作成 * feat(base): openssh-server 追加と ENABLE_SSH による sshd 起動 (PLAN33 PR1) Orca 連携のため base イメージを SSH target 化する。 - containers/base/Dockerfile: 最初の apt-get に openssh-server を追加。 root のうちに /run/sshd と /etc/ssh/sshd_config.d/10-devbase-orca.conf (公開鍵認証のみ・Password 無効・TcpForwarding 有効)を作成。 - containers/base/entrypoint.sh: ENABLE_SSH=true/1 で sshd を起動する ブロックを追加。AI 設定 symlink 生成後(~/.ssh が /persistent/ai/.ssh へ張り替え済み)かつ exec "$@" 前に配置。host key を /persistent/ai/ssh に永続化・復元し、SSH_AUTHORIZED_KEYS を authorized_keys へ展開。 - docs/user/container-operations.md: openssh-server 同梱と ENABLE_SSH、 host key 永続化、base 変更に build --no-cache が要る旨を追記。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: PLAN33-docs Draft PR 作成 * docs: Orca 接続ガイドを追加し README/docs 索引に導線を追記 コンテナ内 sshd を publish して Orca の SSH target として接続する エンドツーエンドの手順を docs/user/orca.md に追加。base 再ビルド → env init(公開鍵)→ ENABLE_SSH で up → devbase orca sync → Orca への import → worktree 作成までを網羅。macOS 直結 / Windows→macOS(SSH トンネル・Tailscale)の 2 パターン、環境変数一覧、 隔離設計、Ports tab、トラブルシュート(docker exec/ProxyCommand を 採らない理由・host key 永続化)を記載。README.md と docs/README.md の 機能一覧・ドキュメント索引に導線を追記。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Orca からコンテナへ SSH 接続するための、ホスト側の隔離 SSH config 生成と `devbase orca` コマンド、up/down フックを追加する。 - `devbase orca sync/prune/status`: 稼働中の SSH publish 済みコンテナを docker inspect で列挙し (コンテナ名の dash split はせず compose ラベルと 22/tcp publish で判定)、`~/.config/devbase/orca/ssh_config` を全再生成する。 他ホストを一切書かないため Orca への import で隔離が成立する。 - up 完了後に ENABLE_SSH 有効時のみ orca sync、down 後に orca prune を best-effort で呼ぶ (失敗しても up/down の戻り値は変えない)。 - collectors/orca.py: laptop の公開鍵を SSH_AUTHORIZED_KEYS として、 HostName 用 DEVBASE_ORCA_HOSTNAME を env init で収集する。 - keys.py に SSH_AUTHORIZED_KEYS / DEVBASE_ORCA_HOSTNAME を追加。 - cli.py / bin/devbase に orca サブコマンドを配線。 - tests/commands/test_orca.py: レンダリング・隔離・prune・列挙の単体テスト (実 docker は呼ばず fake targets / サンプル JSON を注入)。 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
release ブランチが self-documenting になるよう、実装の設計根拠 (PR 分割計画・ 設計判断・E2E テスト計画) と元 issue / アドバイスを issues/ 配下に追加する。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 1 | codex | REQUEST_CHANGES
修正が必要な問題を4件インラインで指摘しました。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 1 | gemini | APPROVE
本PRにおける変更は既存アーキテクチャと整合しており、副作用や構造的なリスクは見当たりません。修正を提案する事項はありません。
- 隔離: dev コンテナへ dev.devbase.ssh ラベルを付与し、_parse_inspect の 必須条件に追加。22/tcp を publish する他 Compose プロジェクトの混入を防ぐ。 - ポート衝突: allocate_ssh_host_port を追加し、決定的ポートを優先しつつ 同一生成内 + 他プロジェクト稼働 publish (best-effort docker 照会) と衝突する 場合は線形探索で回避。決定性は衝突が無い限り保つ。 - docs: env init が収集するのは Mac の公開鍵である点を明記し、Windows の Orca では Windows の公開鍵を SSH_AUTHORIZED_KEYS に登録する手順・複数鍵対応・ IdentityFile の対応関係を追記。 - エラーハンドリング: _running_ssh_targets が列挙失敗時に None を返し、 regenerate_config は OrcaEnumerationError を送出して既存 config を保持。 sync/prune CLI は非ゼロ終了、up/down フックは warning のみ。 tests: 889 passed (+10) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🔧 /ndf:fix サマリ (round 1)codex の指摘 4 件 (すべて major) にコード修正で対応しました。
対応内容
commit / CI
4 スレッドすべてに返信・resolve 済みです。 |
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 2 | codex | REQUEST_CHANGES
スケール経路で既存 SSH ポートを維持し、新規インスタンス起動後に Orca config を同期する必要があります。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 2 | gemini | REQUEST_CHANGES
Orca 連携における SSH config の自動生成・ポート計算処理についてレビューしました。隔離 config によってユーザー側の設定を汚さない方針は堅牢ですが、オンラインスケール時のポート計算や一部の連携においてエッジケースが存在するため、以下の修正を提案します。
devbase scale時の他コンテナのポート取得処理 (docker ps) が自プロジェクトの稼働中ポートも含んでしまうため、スケール実行時にポート衝突判定が起こり、意図せぬコンテナの Recreate が発生する点を修正してください。devbase scale後に Orca config の更新が漏れているため同期処理を追加してください。
cross-review round 2 の指摘 3 件に対応。 A [major/正確性] SSH ポート衝突回避が自プロジェクトの稼働ポートまで数え、 devbase scale で既存 dev-1..N の決定的ポートが +1 ずれて --no-recreate と 不整合になる問題を修正。_running_published_host_ports に exclude_project 引数を 追加し com.docker.compose.project ラベルで自プロジェクトを除外。up/scale の 呼び出し側から現在の project_name を渡す。 B [major/状態同期] cmd_scale がスケールアウト後に Orca config を再生成せず、 追加インスタンスが手動 sync まで現れない問題を修正。up 経路同様に成功時 best-effort で _maybe_orca_sync() を呼ぶ。 C [minor/UX] 生成 config の IdentityFile を ~/.ssh/id_ed25519 固定にしていたため id_rsa のみのユーザーで不一致警告が出る問題を修正。IdentityFile 行を出力せず SSH クライアント/Orca の既定鍵解決に委ねる。docs/user/orca.md も追随。 テスト: A の自プロジェクト除外/他プロジェクト衝突と C の IdentityFile 非出力を追加。 uv run pytest tests/ -q は 895 passed。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🔧 /ndf:fix サマリ (round 2)cross-review round 2 の指摘に対応し 修正 commit:
重要度別: critical 0 / major 2 / minor 1 / nit 0(重複スレッド含め 5 スレッドを reply + resolve) テスト: A の自プロジェクト除外・他プロジェクト衝突、C の IdentityFile 非出力を追加。 CI: commit |
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 3 | codex | REQUEST_CHANGES
SSH host key の初期生成をインストール単位の固有鍵にし、scale の同時起動でも共有永続領域を安全に初期化してください。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 3 | gemini | APPROVE
モジュール外から利用されるプライベート関数の存在と、一部の型アノテーションの不一致を指摘しています。機能自体の実装・テスト・ドキュメントは非常に丁寧に書かれており問題ありません。
クロスレビュー round 3 の指摘 3 件に対応。 - [major/security] entrypoint.sh: openssh-server がビルド時に生成する /etc/ssh/ssh_host_*_key を初回起動時に破棄してから ssh-keygen -A で再生成し、 イメージ由来の予測可能な共通 host key が全 install で共有される問題を修正。 生成/復元+永続化を flock で直列化し、同一ボリューム共有時の競合 (TOCTOU) を回避。 - [minor] compose._running_published_host_ports を public 名 get_running_published_host_ports へ改名 (定義/import/呼出/テスト全箇所)。 - [minor] cmd_orca の targets_provider 型注釈を Optional[Callable[[], Optional[List[SSHTarget]]]] へ修正 (None 返却に整合)。 - docs: host key が install ごとに一意生成される旨を追記 (orca.md / container-operations.md)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🔧 /ndf:fix サマリ (round 3)クロスレビュー round 3 の指摘 3 件すべてに対応しました。
severity 内訳: critical 0 / major 1 / minor 2 / nit 0 検証
docs ( fix commit:
|
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 4 | codex | REQUEST_CHANGES
scale 2 以上の target 識別と、永続化された認証鍵の失効処理を修正してください。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 4 | gemini | REQUEST_CHANGES
Windows 環境での USERNAME 参照起因で、Orca からの SSH 接続が失敗する不具合が見つかりました。コンテナのユーザー(ubuntu 固定)と乖離するため修正が必要です。
クロスレビュー round4 の major 指摘 3 件に対応。 1. [correctness] scale>=2 で Orca Host が衝突する問題を修正。 generate_scaled_compose は dev-1..N を別サービスとして展開するため compose の container-number が全て 1 になり、index が全 target で 1 に 潰れて Host devbase-<project>-1 が衝突していた。SSH publish 時に dev.devbase.index ラベルを付与し、_parse_inspect はこのラベルから index を読む (未設定時は container-number へフォールバック)。 2. [security] SSH_AUTHORIZED_KEYS を空にしても失効鍵で login できる問題を修正。 ~/.ssh は永続ストレージへの symlink のため、env を空にしても前回の authorized_keys が残っていた。空のときは rm -f で永続鍵を削除して失効を反映する。 3. [correctness] User にホストの USERNAME を使うと SSH 失敗する問題を修正。 Windows 上の Orca ホストでは USERNAME が Windows アカウント名になるが コンテナのログインユーザーは常に ubuntu。ambient な USERNAME は読まず ubuntu を既定とし、上書きは devbase 専用の DEVBASE_ORCA_USER のみに限定する。 keys.py に DEVBASE_ORCA_USER を追加し docs/user/orca.md にも記載。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🔧 /ndf:fix サマリ (round 4)round 4 の major 指摘 3 件をすべて修正しました。 重要度別: critical 0 / major 3 / minor 0 / nit 0 — 対応 3 / 見送り 0 / 却下 0
検証: commit: CI: 起動待ち (結果は待たずに報告)。3 スレッドは reply + resolve 済み。 |
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 5 | codex | REQUEST_CHANGES
全プロジェクト横断の SSH config 生成で、プロジェクト別の接続属性を entry ごとに保持するよう修正が必要です。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 5 | gemini | COMMENT
Orca の SSH 接続基盤と config 自動同期の追加 PR として、意図された設計と既存機能との統合が非常に綺麗に実装されています。
SSH config の隔離、host key の一意生成+永続化による known_hosts 警告の回避、allocate_ssh_host_port におけるホストポートの決定的な算出・衝突回避など、細かい部分まで丁寧に対応されており堅牢です。
数点、状態の同期漏れ(ENABLE_SSH をオフにした際の古い target の残留)と、環境変数のパース時のエラーハンドリングについて修正を提案します。
- cross-project sync が全エントリへ実行プロジェクトの User を一律適用し、 container user の異なる別プロジェクトのエントリがログイン不能になる問題を修正。 compose 生成時に dev.devbase.user ラベルへ各プロジェクト自身の解決済みユーザーを 焼き込み、_parse_inspect が per-target で読み取って SSHTarget.user に持たせる。 _render_config はエントリ毎に User を出力する。 - ENABLE_SSH を true→false に切り替えて再 up した際、停止したコンテナのエントリが Orca config に残る問題を修正。_maybe_orca_sync を「SSH 有効 または config 既存」で 再生成するよう変更。config 未作成の純粋な非 Orca ユーザーでは従来どおり何もしない (無用なファイル生成を避ける)。orca.config_exists() を追加。 - DEVBASE_SSH_PORT_BASE が非整数だと up が stacktrace で落ちる問題を修正。 int 変換を try/except で握り DockerError に変換 (変数名と値を明示)。確保後の ホストポートが 1..65535 を超える場合も DockerError にする。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🔧 /ndf:fix サマリ (round 5)commit:
対応内容
テスト
CIローカルの pytest はグリーン。CI の完了は待たずに報告しています (別途確認してください)。 解決済みレビュースレッド: orca.py:227 / container.py:454 / compose.py:238 (codex) / compose.py:238 (gemini) の 4 件。 |
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 6 | codex | REQUEST_CHANGES
Orca 未利用時の down がユーザー設定領域を変更しないよう、prune の実行条件を修正してください。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 6 | gemini | REQUEST_CHANGES
devbase down 実行時の _maybe_orca_prune において、非Orcaユーザーの環境(ホームディレクトリ)を汚染してしまう問題が見つかりました。インラインコメントの修正をお願いします。
down 後の Orca SSH config 剪定が regenerate_config() を無条件に呼んでいたため、 Orca/SSH を一切使わないユーザーの devbase down でも毎回 ~/.config/devbase/orca/ ssh_config (親ディレクトリ + ヘッダ) が新規生成されていた。round5 で _maybe_orca_sync に追加した config_exists() ゲートと同じ扱いにし、config が 既に存在するときのみ剪定するよう修正する。剪定ゲートの test を 3 件追加。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🔧 /ndf:fix サマリ (round 6)codex / gemini が同一箇所を指摘 (2 スレッド,
対応内容
検証
CI の完了は待たずに報告しています。 |
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 7 | codex | APPROVE
修正が必要な新規指摘はありません。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 7 | gemini | APPROVE
UI観点での軽微な改善提案を1点のみインラインで残しています。
公開鍵は数百文字・複数行になり得るため、そのまま safe_input の プロンプトへ埋め込むとターミナル表示が崩れる。鍵種別と末尾数文字 + (設定済み) の短縮表示に変更。Enter で維持される既定値 (default 引数) はフル鍵のままで、保存値のセマンティクスは不変。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🔧 最終スイープ (Step 7.5)クロスレビューは収束 (codex / gemini とも APPROVE)。残っていた未解決スレッド 1 件をスイープし、未解決スレッド 0 件 で完了しました。 対応内容
検証
commit: 107acd6 |
Summary
背景 / 解決したい課題
Orca は「SSH target 上に git worktree を作り、AI エージェント (claude / codex / gemini 等) も SSH target 側で動かし、editor/diff だけ手元で使う」リモート開発モデルを採る。現状 devbase が起動するコンテナは SSH で入れないため、Orca から接続してコンテナ内で worktree / エージェントを動かせなかった。
docker exec/ProxyCommand方式は Orca の file explorer / diff / worktree がホスト側を向いてしまい SFTP も使えないため採らず、コンテナ内sshdを publish して「普通の SSH host」として見せる構成にした。変更内容(release ブランチ全体)
openssh-serverを追加し、/etc/ssh/sshd_config.d/に Orca 向け設定(公開鍵認証のみ・Password 無効・AllowTcpForwarding yes)を配置。ENABLE_SSH=trueの opt-in(ENABLE_DINDと同じパターン)で entrypoint が sshd を起動する。host key は/persistent/ai/ssh/に永続化し、再ビルド/再作成でも Orca の known_hosts 警告が出ないようにする。SSH_AUTHORIZED_KEYS(laptop の公開鍵)を~/.ssh/authorized_keys(/persistent/ai/.sshに永続化)へ展開する。devbase up時、ENABLE_SSH有効なら各 dev インスタンスの:22をホストの<bind>:<port>に publish する。ポートは(project, index)から決定的に算出(既定 base2200、down→upを跨いで一定)。bind 既定は127.0.0.1(外部非公開)。~/.config/devbase/orca/ssh_configを稼働中コンテナ(docker inspectの compose ラベル +22/tcppublish で判定)から全生成する。ホストの~/.ssh/configは一切触らないため、Orca にこのファイルだけを import すれば devbase コンテナ以外は見えない(隔離要件)。devbase up/downに best-effort で同期/剪定を連動(失敗しても up/down は倒さない)。devbase orcaコマンド:sync(再生成)/prune(停止分の剪定 = 再生成)/status(config パス・内容・import 手順の表示)。devbase env init: laptop の公開鍵(~/.ssh/id_ed25519.pub→id_rsa.pub)をSSH_AUTHORIZED_KEYSとして収集する collector を追加。docs/user/orca.md(接続ガイド: macOS 直結 / Windows→macOS トンネル・Tailscale、Ports tab、トラブルシュート)+ README 導線。plan:
issues/PLAN33_orca-support.mdTest plan(結合観点のみ/実機・手動)
devbase build --no-cache後に sshd 入りイメージが生成されるENABLE_SSH=trueでdevbase up→ssh -p <port> ubuntu@127.0.0.1 'whoami; git --version'が通るssh ... 'claude --version || codex --version || gemini --version'が通るdevbase orca sync生成ファイルを Orca に import → SSH target Test 成功 / worktree 作成がコンテナ側で走るdevbase down後に Orca エントリが剪定される(devbase orca statusで確認)DEVBASE_ORCA_HOSTNAME(Tailscale)で Orca 接続成功自動テスト
tests/volume/test_compose_ssh_ports.py(ポート publish・決定性)、tests/commands/test_orca.py(config 生成・隔離・剪定)uv run pytest tests/→ 879 passed開発用: 個別 PR(レビュー対象外・全て release へ merge 済み)